﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IURIP;
using System.Xml;
using URIP.Tool;
using Antlr.StringTemplate;

namespace URIP.Core
{
    public class Action : BaseRunable, IAction
    {
        public Action(ITemplate template, IRunable parentRunable) :
            base(template, parentRunable)
        {
            m_actionTemplate = (IActionTemplate)template;
        }

        private List<XmlNode> m_tgtParentNodes = new List<XmlNode>();
        private List<XmlNode> m_tgtRecursiveNodes = new List<XmlNode>();
        private List<string> m_recursiveIDs = new List<string>();
        private IActionTemplate m_actionTemplate = null;

        public XmlNode OriginalDataXml
        {
            get;
            set;
        }
        public IFilter Filter
        {
            get;
            set;
        }
        public List<XmlNode> TgtParentNodes
        {
            get { return m_tgtParentNodes; }
        }
        public XmlNode TgtCurrentParentNode
        {
            get;
            set;
        }
        public List<XmlNode> TgtExtractedListNodes
        {
            get { return m_tgtRecursiveNodes; }
        }
        public List<string> RecursiveIDs
        {
            get { return m_recursiveIDs; }
        }

        protected override void RunAssis()
        {
            string actionName = m_actionTemplate.Name;
            Task.Logger.LogDebug("Start running action '{0}' for target '{0}'", actionName, Target.Name);

            //@@ Transfer information from process
            if (Process != null && Process.OriginalDataXml != null)
            {
                OriginalDataXml = Process.OriginalDataXml;
                Process.OriginalDataXml = null;
            }
            if (Process != null && Process.FilterFromTargetRelationship != null)
            {
                Filter = Process.FilterFromTargetRelationship;
                Process.FilterFromTargetRelationship = null;
            }
            //@@ provideDataNode enable the action can be nested
            XmlNode provideDataNode = ParentRunable.Action == null ? Process.TargetDataXml : ParentRunable.Action.TgtCurrentParentNode;
            m_tgtParentNodes.AddRange(Util.GetXPathList(provideDataNode, m_actionTemplate.ParentXPath));
            Task.Logger.LogInfo("The action {0} will run {1} times!", actionName, m_tgtParentNodes.Count);
            for (int i = 0; i < m_tgtParentNodes.Count; i++)
            {
                //@@ Initialize information when the new loop start
                TgtCurrentParentNode = m_tgtParentNodes[i];
                RecursiveIDs.Clear();
                TgtExtractedListNodes.Clear();
                //@@ Only the first time will probably use the information transfered from process.
                if (i == 0 && Filter == null && OriginalDataXml == null)
                {
                    Filter = this.CreateFilter(TgtCurrentParentNode);
                }
                else
                {
                    Filter = this.CreateFilter(TgtCurrentParentNode);
                    OriginalDataXml = null;
                }

                if (this.CheckOperation())
                {
                    return;
                }
                Task.Logger.LogInfo("Run action {0} at {1} times.", actionName, i + 1);
                this.RunHelper(this.GetFirstChildNode(), TgtCurrentParentNode);
            }

            Task.Logger.LogDebug("Finish action '{0}' for target '{0}'", actionName, Target.Name);
        }
        private Filter CreateFilter(XmlNode parentNode)
        {
            StringHash obj = StringHash.ConvertXMLStructure(parentNode.OuterXml, true);
            StringTemplate st = new StringTemplate(m_actionTemplate.Filter.Query);
            st.SetAttribute("o", obj);
            return new Filter("", "", st.ToString());
        }
    }
}
